const ARRAY_METHOD = [
  "push",
  "pop",
  "shift",
  "unshft",
  "reverse",
  "srot",
  "splice"
];

let array_methods = Object.create(Array.prototype);

ARRAY_METHOD.forEach((method) => {
  array_methods[method] = function () {
    // 调用原来的方法
    for (let i = 0; i < arguments.length; i++) {
      observe(arguments[i]); // 这里还是有个问题 不传不了vm
    }

    let res = Array.prototype[method].apply(this, arguments);
    // Array.prototype[method].call(this,...arguments)  报错 arguments不是真数组 而是类数组 扩展运算符不能这样用
    return res;
  };
});

function defineReactive(target, key, value, enmuerable) {
  // this 指向vue 实例 因为调用时 call 传入了vue 实例

  if (typeof value === "object" && value != null) {
    observe(value); // 递归
  }
  let dep = new Dep();
  Object.defineProperty(target, key, {
    configurable: true,
    enumerable: !!enmuerable,
    get() {
      dep.depend();
      return value;
    },
    set(newValue) {
      // 模板刷新 演示
      // 如何获取vue 实例  watchter
      if (typeof newValue === "object" && newValue != null) {
        observe(newValue); // 将重新赋值的数据变成响应式的，因此传入的是对象重新响应式  没有返回值 重新赋值
      }
      value = newValue;
      console.log("newValue", newValue);
      dep.notify(); // 派发更新, 找到全局的 watcher, 调用 update
      // typeof that.mountComponent() === "function" && that.mountComponent();
    }
  });
}

// function reactify(o, vm) {
//   let keys = Object.keys(o); // 没有对o 响应式处理 只是对o 的成员响应式处理
//   for (let i = 0; i < keys.length; i++) {
//     let key = keys[i];
//     let value = o[key];
//     // 判断属性 是不是引用类似，判断是不是数组
//     // 如果是数组 就要循环数组 ，然后将数组里面的元素响应式化
//     if (Array.isArray(value)) {
//       value.__proto__ = array_methods;
//       for (let j = 0; j < value.length; j++) {
//         reactify(value[j], vm);
//       }
//     } else {
//       // 对象或值类型
//       defineReactive.call(vm, o, key, value, true);
//     }
//   }
// }

function proxy(target, prop, key) {
  Object.defineProperty(target, key, {
    enmuerable: true,
    configurable: true,
    get() {
      return target[prop][key];
    },
    set(newValue) {
      target[prop][key] = newValue;
    }
  });
}
Yvue.prototype.initData = function () {
  // 遍历this._data 成员 进行响应式转化  进行代理
  let keys = Object.keys(this._data);

  // 进行响应式转化
  observe(this._data, this);

  for (let i = 0; i < keys.length; i++) {
    // 进行代理
    proxy(this, "_data", keys[i]);
  }
};
// 将对象o 变成响应式 因为还没引入water 传入 vm 就是vue 实例
function observe(o, vm) {
  // 判断o 是否是个数组
  if (Array.isArray(o)) {
    // 对其每个元素处理i
    o.__proto__ = array_methods;
    for (let i = 0; i < o.length; i++) {
      observe(o[i], vm);
      // defineReactive.call(vm, o, i, o[i], true);
    }
  } else {
    let keys = Object.keys(o);
    for (let i = 0; i < keys.length; i++) {
      let prop = keys[i]; // 属性名
      defineReactive.call(vm, o, prop, o[prop], true);
    }
  }
}
